﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
//using System.Math;

namespace Quest
{
    abstract class Weapon: Mover
    {
        //protected Weapons name;
        //public Weapons Name { get { return name; } }

        //public abstract string Name { get; }
        public abstract Weapons Name { get; }

        protected bool pickedUp; // I adopted "protected" instead of the "public" in the book
        public bool PickedUp { get { return pickedUp; } }

        public Weapon(Game game, Point point): base (game, point)
        {
            pickedUp = false;
        }

        public void PickUpWeapon()
        {
            pickedUp = true;
        }

        public abstract void Attack(Direction direction, Random random);
        public void Attack(Direction direction, List<int> turnDirections, Random random, int radius, int maxDamage)
        {
            List<Direction> attackDirections = new List<Direction>();
            foreach (int turnDirection in turnDirections)
                attackDirections.Add(getDirection(direction, turnDirection));

            foreach (Direction attackDirection in attackDirections)
                if (DamageEnemy(attackDirection, radius, maxDamage, random))
                    return;
        }

        protected bool DamageEnemy(Direction direction, int radius, int damage, Random random)
        {
            Point target = game.PlayerLocation;
            //for (int distance = 0; distance < radius / 2; distance++) // AndrewStellman's http://forums.oreilly.com/topic/91946-the-quest/ post #5 suggestion: but the player results too weak!
            for (int distance = 0; distance < radius; distance++)
                {
                foreach (Enemy enemy in game.Enemies)
                    if (Nearby(enemy.Location, target, distance))
                    {
                        enemy.Hit(damage, random);
                        return true;
                    }
                target = Move(direction, target, game.Boundaries);
            }
            return false;
        }


        //protected bool DamageEnemy(Direction direction, int radius, int damage, Random random)
        //{
        //    Point target = game.PlayerLocation;
        //    Enemy enemyToHit = enemyInRange(radius, target);
        //    if (!(enemyToHit == null))
        //    {
        //        enemyToHit.Hit(damage, random);
        //        return true;
        //    }
        //    target = Move(direction, target, game.Boundaries);

        //    return false;
        //}

        //protected Enemy enemyInRange(int radius, Point playerLocation)
        //{
        //    int maxDistance = 0;
        //    int distance;
        //    Enemy nearestEnemy = null;
        //    foreach (Enemy enemy in game.Enemies)
        //    {
        //        distance = getDistance(enemy.Location, playerLocation);
        //        if (distance > maxDistance)
        //        {
        //            maxDistance = distance;
        //            nearestEnemy = enemy;
        //        }
        //    }
        //    if (maxDistance <= radius * radius)
        //        return nearestEnemy;
        //    else
        //        return null;
        //}

        //private int getDistance(Point point1, Point point2)
        //{
        //    int dX = point1.X - point2.X;
        //    int dY = point1.y - point2.y;
        //    return dX * dX + dY * dY;
        //}

        private Direction getDirection(Direction direction, int turn)
        {
            if (turn != 0)
            {
                int directionValue = (int)direction + turn;
                int newDirectionValue;
                if (directionValue>=0)
                    Math.DivRem(directionValue, 4, out newDirectionValue);
                else
                {
                    Math.DivRem(directionValue, 4, out newDirectionValue);
                    newDirectionValue = 4 + newDirectionValue;
                }
                return (Direction)newDirectionValue;
            }
            return direction;
        }

    }
}
